#if defined (__MACH__) && defined (__APPLE__)
#else
#include <sys/prctl.h>
#endif
#include "common_log.h"
#include "sf_thread.h"

SimpleThread::SimpleThread() :
    mRunning(false),
    mJoin(false)
{
    // GEN_Printf(LOG_DEBUG, "SimpleThread: %p", this);
    pthread_mutex_init(&mMutex, NULL);
}

void* SimpleThread::callback(void* arg)
{
    SimpleThread* thread = (SimpleThread*) arg;

    thread->run();

    pthread_mutex_lock(&thread->mMutex);
    thread->mRunning = false;

    if (!thread->mJoin) {
        pthread_detach(pthread_self());
    }
    pthread_mutex_unlock(&thread->mMutex);

    pthread_exit(NULL);
    return NULL;
}


SimpleThread::~SimpleThread()
{
    if (mRunning)
    {
        GEN_Printf(LOG_WARN, "Thread %lx went out of scope while running!", (unsigned long) mThread);
    }

    pthread_mutex_destroy(&mMutex);
}

bool SimpleThread::start()
{
    pthread_mutex_lock(&mMutex);

    //GEN_Printf(LOG_DEBUG, "SimpleThread::start: %p", this);
    if (!mRunning)
    {
    	int ret = pthread_create(&mThread, NULL, callback, this);
        if (ret != 0)
        {
            GEN_Printf(LOG_WARN, "pthread_create failed, %d, %s", errno, strerror(errno));
        }

        mJoin = false;
    	mRunning = (ret == 0);
    }

    pthread_mutex_unlock(&mMutex);	

    return mRunning;
}

bool SimpleThread::join()
{
    int ret = 0;

    pthread_mutex_lock(&mMutex);
    if (mRunning)
    {
        mJoin = true;

        pthread_mutex_unlock(&mMutex);

        if (mRunning)
        {
            ret = pthread_join(mThread, NULL);
        }

        pthread_mutex_lock(&mMutex);
        if (ret == 0)
        {
	        mRunning = false;
	    }
    }
    pthread_mutex_unlock(&mMutex);

    return (ret == 0);
}

unsigned long SimpleThread::id()
{
    return (unsigned long) mThread;
}

void SimpleThread::yield()
{
    sched_yield();
}

bool SimpleThread::setPriority(int priority)
{
    struct sched_param params;
    params.sched_priority = priority;
    int ret = pthread_setschedparam(mThread, SCHED_FIFO, &params);
    return ret == 0;
}

bool SimpleThread::setName(const char* name)
{
#ifdef HAVE_PTHREAD_SETNAME_NP 
    return pthread_setname_np(mThread, name) == 0;
#else
    if(name)
    {
#if !defined (__MACH__) && !defined (__APPLE__)
        prctl(PR_SET_NAME, name);
#endif
    }
    return true;
#endif
}

unsigned long SimpleThread::selfId()
{
    return reinterpret_cast<unsigned long>(pthread_self());
}

void SimpleThread::cancel()
{
    //表示不是android系统的编译
#ifndef ANDROID
    pthread_cancel(mThread);
#endif
}

void SimpleThread::msleep(int msec)
{
    ::usleep(msec * 1000);
}

void SimpleThread::sleep(int sec)
{
    ::sleep(sec);
}

bool SimpleThread::isCommonContent()
{
    return (pthread_self() == mThread) ? true : false;
}
